﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Runda.EShop.Common.Utility;
using System.Data;
using Runda.EShop.Common.Entity;
using Runda.EShop.Bll;

namespace Runda.EShop.Service.WMS
{
   public  class InnerService
    {
        private int ThreadCount;
        private bool IsRunning;
        private List<System.Threading.Thread> ThreadList;   //线程列表
        private Queue<SysOrderServiceStatusEntity> MessageQueue;    //订单队列
        private static object LockKey = new object();  //用于控制多线程并发
        private int ReadMailInterval = 60000; //订单队列更新时间间隔30秒
        private int SendMailInterval = 2000; //订单队列发送订单时间间隔3秒
        private int MsgQueueLenght = 100; //订单队列长度

        public InnerService(int threadCount)
        {
            this.ThreadCount = threadCount;
            this.ThreadList = new List<System.Threading.Thread>();

            //添加获取数据线程
            this.ThreadList.Add(new System.Threading.Thread(GetMessageQueue));

            //添加发订单线程
            for (int i = 0; i < threadCount; i++)
            {
                this.ThreadList.Add(new System.Threading.Thread(SendMail));
            }

            MessageQueue = new Queue<SysOrderServiceStatusEntity>();
        }

        public void Start()
        {
            if (IsRunning)
                return;

            IsRunning = true;
            foreach ( System.Threading.Thread thread in this.ThreadList)
            {
                //启动所有线程
                thread.Start();
                System.Threading.Thread.Sleep(100);
            }
        }

        public void Sotp()
        {
            IsRunning = false;

            System.Threading.Thread.Sleep(1000);

            foreach (System.Threading.Thread thread in this.ThreadList)
            {
                try
                {
                    thread.Abort();
                }
                catch
                {
                }

            }
        }


        /// <summary>
        /// 订单队列中没有订单时从数据库中获取订单，并放入订单队列中；
        /// </summary>
        private void GetMessageQueue()
        {
            while (IsRunning)
            {
                try
                {

                    lock (LockKey)
                    {
                        if (MessageQueue.Count <= 0)
                        {
                            //获取新的订单
                            SysOrderServiceStatusBll bll = new SysOrderServiceStatusBll();
                            List<SysOrderServiceStatusEntity> list = bll.GetAll<SysOrderServiceStatusEntity>(" and Status in (0,2) ");//and NextTime <= '"+DateTime.Now+"'");
                            if (list != null)
                            {
                                foreach(SysOrderServiceStatusEntity entity in list)
                                {
                                    //增加订单队列
                                    MessageQueue.Enqueue(entity);
                                }
                            }
                        }

                    }

                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex.Message);
                }
                //取订单间隔
                System.Threading.Thread.Sleep(ReadMailInterval);
            }

        }

        /// <summary>
        /// 订单发送线程处理函数，基本思路为：
        /// 2、正在发送的订单放在发送列表中，需要保证这些订单不会被再次从数据库中取出
        /// 3、订单发送成功需要更新订单发送状态到数据库中
        /// 4、无论订单是否发送成功，都需要将订单从发送列表中去除
        /// </summary>
        private void SendMail()
        {
            while (IsRunning)
            {
                try
                {
                    SysOrderServiceStatusEntity row = null;

                    //从订单队列中获取订单
                    lock (LockKey)
                    {
                        if (MessageQueue.Count > 0)
                        {
                            row = MessageQueue.Dequeue();
                        }
                    }

                    if (row != null)
                    {
                        OperateResult result = new OperateResult(); 
                        try
                        {
                            Runda.EShop.Bll.ServiceAdapter.WMSServiceAdapter adp = new Bll.ServiceAdapter.WMSServiceAdapter();
                            result = adp.PutSOData(row.OrderID);  

                        }
                        catch (Exception ee)
                        {
                            //出现异常 记录事件日志 
                            LogHelper.Write("调用WMS服务失败，OrderID:" + row.OrderID + "，信息："+ee.Message +"。StackTrace:" + ee.StackTrace);
                        }

                        try
                        {
                            SysOrderServiceStatusBll bll = new SysOrderServiceStatusBll();
                            if (result.IsSuccess)
                            {
                                bll.UpdateOrderServiceStatus(row, EnumHelper.OrderServiceStatus.Success, result.Message);
                            }
                            else
                            {
                                bll.UpdateOrderServiceStatus(row, EnumHelper.OrderServiceStatus.Fail, result.Message);
                            }
                        }
                        catch (Exception ee)
                        {
                            LogHelper.Write("调用WMS服务后更新订单状态失败，OrderID:" + row.OrderID + "，信息：" + ee.Message);
                        }

                        //发送订单时间间隔
                        System.Threading.Thread.Sleep(SendMailInterval);

                    }
                    else
                    {
                        //如果有没有数据等待时间间隔
                        int TempInterval = (int)(ReadMailInterval / (2 * ThreadCount));
                        System.Threading.Thread.Sleep(TempInterval);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex.Message);
                }
            }
        }


        private Exception GetInnerException(Exception ex)
        {
            while (ex.InnerException != null)
            {
                ex = ex.InnerException;
            }
            return ex;
        }
    }
}
